﻿using System;
using System.Diagnostics;
using System.IO;

namespace SimpleDbBrowser.ViewModel.Diagnostics
{
    /// <summary>
    /// Directs tracing or debugging in a way identical to a 
    /// TextWriterTraceListener, but also fires an event when the underlying 
    /// text writer has been written to.
    /// </summary>
    public sealed class ObservableTextWriterTraceListener : TextWriterTraceListener
    {
        /// <summary>
        /// Initializes a new instance of the ObservableTextWriterTraceListener class.
        /// </summary>
        public ObservableTextWriterTraceListener()
        {
        }

        /// <summary>
        /// Initializes a new instance of the ObservableTextWriterTraceListener class.
        /// </summary>
        /// <param name="fileName">
        /// The name of the file the ObservableTextWriterTraceListener writes to.
        /// </param>
        public ObservableTextWriterTraceListener(string fileName)
            : base(fileName)
        {
        }

        /// <summary>
        /// Initializes a new instance of the ObservableTextWriterTraceListener class.
        /// </summary>
        /// <param name="stream">
        /// A Stream that represents the stream the ObservableTextWriterTraceListener writes to.
        /// </param>
        public ObservableTextWriterTraceListener(Stream stream)
            : base(stream)
        {
        }

        /// <summary>
        /// Initializes a new instance of the ObservableTextWriterTraceListener class.
        /// </summary>
        /// <param name="writer">
        /// A TextWriter that receives the output from the ObservableTextWriterTraceListener.
        /// </param>
        public ObservableTextWriterTraceListener(TextWriter writer)
            : base(writer)
        {
        }

        /// <summary>
        /// Initializes a new instance of the ObservableTextWriterTraceListener class.
        /// </summary>
        /// <param name="fileName">
        /// The name of the file the ObservableTextWriterTraceListener writes to.
        /// </param>
        /// <param name="name">
        /// The name of the new instance.
        /// </param>
        public ObservableTextWriterTraceListener(string fileName, string name)
            : base(fileName, name)
        {
        }

        /// <summary>
        /// Initializes a new instance of the ObservableTextWriterTraceListener class.
        /// </summary>
        /// <param name="stream">
        /// A Stream that represents the stream the ObservableTextWriterTraceListener writes to.
        /// </param>
        /// <param name="name">
        /// The name of the new instance.
        /// </param>
        public ObservableTextWriterTraceListener(Stream stream, string name)
            : base(stream, name)
        {
        }

        /// <summary>
        /// Initializes a new instance of the ObservableTextWriterTraceListener class.
        /// </summary>
        /// <param name="writer">
        /// A TextWriter that receives the output from the ObservableTextWriterTraceListener.
        /// </param>
        /// <param name="name">
        /// The name of the new instance.
        /// </param>
        public ObservableTextWriterTraceListener(TextWriter writer, string name)
            : base(writer, name)
        {
        }

        /// <summary>
        /// Occurs when a message has been written to the ObservableTextWriterTraceListener.
        /// </summary>
        public event EventHandler TracedMessage;

        /// <summary>
        /// Writes a message to this instance's Writer.
        /// </summary>
        /// <param name="message">
        /// A message to write.
        /// </param>
        public override void Write(string message)
        {
            base.Write(message);

            this.OnTracedMessage(EventArgs.Empty);
        }

        /// <summary>
        /// Writes a message to this instance's WRiter followed by a line 
        /// terminator.  The default line terminator is a carriage return 
        /// followed by a line feed (\r\n).
        /// </summary>
        /// <param name="message">
        /// A message to write.
        /// </param>
        public override void WriteLine(string message)
        {
            base.WriteLine(message);

            this.OnTracedMessage(EventArgs.Empty);
        }

        /// <summary>
        /// Fires the TracedMessage event.
        /// </summary>
        /// <param name="args">
        /// The event's arguments.
        /// </param>
        private void OnTracedMessage(EventArgs args)
        {
            var tmp = this.TracedMessage;
            if (tmp != null)
            {
                tmp(this, args ?? EventArgs.Empty);
            }

            return;
        }
    }
}